package com.nbjtjc.safe.service.danger;

import cn.hutool.core.collection.CollectionUtil;
import com.nbjtjc.safe.bean.Result;
import com.nbjtjc.safe.mapper.danger.DangerInspectTableLabelMapper;
import com.nbjtjc.safe.model.danger.DangerInspectTableLabel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.naming.Name;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @auther guqianbin
 * @date 2018/7/27 10:45
 **/
@Service
public class DangerInspectTableLabelService {

    @Autowired
    private DangerInspectTableLabelMapper dangerInspectTableLabelMapper;

    //TODO 更新缓存,d多线程调用时，如何只调用一个，其他的等待
    @CacheEvict(value = "dangerInspectTableLabel", key = "#dangerInspectTableLabel.companyId")
    public Result add(DangerInspectTableLabel dangerInspectTableLabel) {

        dangerInspectTableLabelMapper.insertSelective(dangerInspectTableLabel);
        return Result.success(dangerInspectTableLabel);
    }

    public Result update(DangerInspectTableLabel dangerInspectTableLabel) {

        //TODO
        dangerInspectTableLabelMapper.updateByPrimaryKeySelective(dangerInspectTableLabel);
        return Result.res();
    }

    public List<DangerInspectTableLabel> find(DangerInspectTableLabel dangerInspectTableLabel) {
        List<DangerInspectTableLabel> dangerInspectTableLabels = dangerInspectTableLabelMapper.select(dangerInspectTableLabel);
        return dangerInspectTableLabels;
    }

    @Cacheable(value = "dangerInspectTableLabel", key = "#companyId")
    public List<DangerInspectTableLabel> getLabelStructure(int companyId) {
        DangerInspectTableLabel dangerInspectTableLabel = new DangerInspectTableLabel();
        dangerInspectTableLabel.setCompanyId(companyId);
        List<DangerInspectTableLabel> dangerInspectTableLabels =
                dangerInspectTableLabelMapper.select(dangerInspectTableLabel);
        Map<Integer, List<DangerInspectTableLabel>> parentIdLabelMap = new HashMap<>();
        dangerInspectTableLabels.forEach(tableLabel -> {
            if (!parentIdLabelMap.containsKey(tableLabel.getParentId())) {
                List<DangerInspectTableLabel> tableLabels = new ArrayList<>();
                tableLabels.add(tableLabel);
                parentIdLabelMap.put(tableLabel.getParentId(), tableLabels);
            } else {
                parentIdLabelMap.get(tableLabel.getParentId()).add(tableLabel);
            }
        });
        List<DangerInspectTableLabel> topLabels = new ArrayList<>();
        if (parentIdLabelMap.containsKey(0)) {
            topLabels = parentIdLabelMap.get(0);
            compareSubLabels(topLabels, parentIdLabelMap);
        }
        return topLabels;
    }

    @Transactional
    public boolean copyLabelStructure(int fromCompanyId, int toCompanyId) {
        List<DangerInspectTableLabel> fromDangerInspectTableLabels = getLabelStructure(fromCompanyId);
        List<DangerInspectTableLabel> insertLabels = new ArrayList<>();
        fromDangerInspectTableLabels.forEach(fromLabel -> {
            DangerInspectTableLabel toLabel = new DangerInspectTableLabel();
            toLabel.setLabel(fromLabel.getLabel());
            toLabel.setCompanyId(toCompanyId);
            toLabel.setParentId(0);
            constructTableLabels(fromLabel, toLabel, toCompanyId);
            insertLabels.add(toLabel);
        });
        insertTableLabels(insertLabels);
        return true;
    }

    /**
     * 构建已经插入过得标签结构
     *
     * @param labels
     * @param parentIdLabelMap
     */
    private void compareSubLabels(List<DangerInspectTableLabel> labels, Map<Integer, List<DangerInspectTableLabel>> parentIdLabelMap) {
        labels.forEach(label -> {
            if (parentIdLabelMap.containsKey(label.getId())) {
                List<DangerInspectTableLabel> dangerInspectTableLabels = parentIdLabelMap.get(label.getId());
                label.setDangerInspectTableLabels(dangerInspectTableLabels);
                compareSubLabels(label.getDangerInspectTableLabels(), parentIdLabelMap);
            }
        });
    }

    /**
     * 构建复制标签的结构，但还未插入
     *
     * @param fromLabel
     * @param toLabel
     * @param companyId
     */
    private void constructTableLabels(DangerInspectTableLabel fromLabel, DangerInspectTableLabel toLabel, int companyId) {
        if (CollectionUtil.isNotEmpty(fromLabel.getDangerInspectTableLabels())) {
            List<DangerInspectTableLabel> dangerInspectTableLabels = new ArrayList<>();
            fromLabel.getDangerInspectTableLabels().forEach(label -> {
                DangerInspectTableLabel dangerInspectTableLabel = new DangerInspectTableLabel();
                dangerInspectTableLabel.setLabel(label.getLabel());
                dangerInspectTableLabel.setCompanyId(companyId);
                constructTableLabels(label, dangerInspectTableLabel, companyId);
                dangerInspectTableLabels.add(dangerInspectTableLabel);
            });
            toLabel.setDangerInspectTableLabels(dangerInspectTableLabels);
        }
    }

    /**
     * 按层标签结构层次插入标签
     * —2
     * 1—       —4
     * —3—
     * —5
     * 如上所示，先插入1，再插入2,3，再插入4,5，按层次插入
     */
    private void insertTableLabels(List<DangerInspectTableLabel> insertLabels) {
        dangerInspectTableLabelMapper.insertList(insertLabels);
        List<DangerInspectTableLabel> toInsertLabels = new ArrayList<>();
        insertLabels.forEach(label -> {
            if (CollectionUtil.isNotEmpty(label.getDangerInspectTableLabels())) {
                label.getDangerInspectTableLabels().forEach(insertLabel -> {
                    insertLabel.setParentId(label.getId());
                    toInsertLabels.add(insertLabel);
                });
            }
        });
        if (CollectionUtil.isNotEmpty(toInsertLabels)) {
            insertTableLabels(toInsertLabels);
        }
    }
}
